﻿// 功能：
// 描述：
// 作者：温伟鹏
// 日期：2010/6/2 11:04:44

using System;
using System.Collections.Generic;
using System.Drawing;
using MeizuSDK.Drawing;
using System.Diagnostics;

namespace MeizuSDK.Presentation
{
    /// <summary>
    /// 列表类型控件基类
    /// </summary>
    public abstract class ListControlBase : Control
    {
        #region 事件
        /// <summary>
        /// 当用户点击列表控件时引发此事件
        /// </summary>
        public event EventHandler<ListBoxClickEventArgs> Click;
        /// <summary>
        /// 当列表绘制列表项时触发此事件
        /// </summary>
        public event DrawItemEventHandler DrawItem;
        /// <summary>
        /// 列表项被选中后触发此事件
        /// </summary>
        public event ItemSelectedEventHandler ItemSelected;
        #endregion

        #region 私有变量
        private int lastClickedItemIndex = -1;
        /// <summary>
        /// 列表项文本大小
        /// </summary>
        private float fontSize;
        /// <summary>
        /// 列表项集合
        /// </summary>
        private ListItemCollection items;
        /// <summary>
        /// 是否由用户自定义绘制列表项
        /// </summary>
        private bool ownerDraw;
        #endregion

        #region 公共属性
        /// <summary>
        /// 获取一个值，指示鼠标左键是否按下
        /// </summary>
        public override bool IsLButtonDown
        {
            get
            {
                return MouseDown;
            }
        }
        /// <summary>
        /// 获取最近一次点击的项目索引值
        /// </summary>
        public int LastClickedIndex
        {
            get
            {
                return lastClickedItemIndex;
            }
            protected set
            {
                this.lastClickedItemIndex = value;
            }
        }
        /// <summary>
        /// 获取或设置列表当前选中的项索引
        /// </summary>
        public abstract int SelectedIndex
        {
            get;
            set;
        }
        /// <summary>
        /// 获取列表当前选中的列表项
        /// </summary>
        public ListItem SelectedItem
        {
            get
            {
                int index = SelectedIndex;

                return Items[index];
            }
        }
        /// <summary>
        /// 获取列表控件的列表项集合
        /// </summary>
        public virtual ListItemCollection Items
        {
            get
            {
                if (items == null)
                {
                    items = new ListItemCollection(this);
                }
                return items;
            }
        }
        /// <summary>
        /// 获取或设置列表项默认高度
        /// </summary>
        public abstract int DefaultItemHeight
        {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置一个标志，指示列表是否绘制列表线
        /// </summary>
        public abstract bool GridLines
        {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置一个标志，指示列表是否绘制额外列表线
        /// </summary>
        public abstract bool UltraGridLines
        {
            get;
            set;
        }
        /// <summary>
        /// 获取或设置一个值，指示是否由用户自定义绘制列表项
        /// </summary>
        public virtual bool OwnerDrawItem
        {
            get
            {
                return this.ownerDraw;
            }
            set
            {
                if (value != this.ownerDraw)
                {
                    this.ownerDraw = value;
                    Invalidate();
                    Update();
                }
            }
        }
        #endregion

        #region 构造函数
        /// <summary>
        /// 构造列表控件基类实例
        /// </summary>
        public ListControlBase()
        {
            this.fontSize = 18;
        }
        #endregion

        #region 函数

        #region 内部函数
        /// <summary>
        /// 添加列表项
        /// </summary>
        /// <param name="text">列表项文本</param>
        internal abstract void AddItem(string text);
        /// <summary>
        /// 移除指定索引的列表项
        /// </summary>
        /// <param name="index"></param>
        internal abstract void RemoveItem(int index);
        /// <summary>
        /// 移除所有的列表项
        /// </summary>
        internal abstract void RemoveAllItems();
        /// <summary>
        /// 列表项被选中委托实现函数
        /// </summary>
        /// <param name="nIndex"></param>
        /// <param name="xPos"></param>
        /// <param name="yPos"></param>
        private void InternalItemSelect(int nIndex, int xPos, int yPos)
        {
            if (ContainsItem(nIndex))
            {
                OnItemSelected(new ItemSelectedEventArgs(this, nIndex, xPos, yPos));
            }
        }
        /// <summary>
        /// 将指定索引的列表项设置为选中状态
        /// </summary>
        /// <param name="nIndex"></param>
        internal void InternalItemSelect(int nIndex)
        {
            InternalItemSelect(nIndex, (int)LastX, (int)LastY);
        }
        /// <summary>
        /// 列表项重绘委托实现函数
        /// </summary>
        /// <param name="hdcDst"></param>
        /// <param name="nIndex"></param>
        /// <param name="prcItem"></param>
        /// <param name="prcWin"></param>
        /// <param name="prcUpdate"></param>
        internal void InternalDrawItem(IntPtr hdcDst, int nIndex, ref RECT prcItem, ref RECT prcWin, ref RECT prcUpdate)
        {
            if (hdcDst == IntPtr.Zero)
                return;

            try
            {
                if (OwnerDrawItem)
                {
                    using (Graphics g = Graphics.FromHdc(hdcDst))
                    {
                        DrawItemEventArgs e = new DrawItemEventArgs(g, nIndex, prcItem.ToRectangle(), prcWin.ToRectangle(), prcUpdate.ToRectangle());
                        // 绘制列表项
                        OnDrawItem(e);
                    }
                }
                else
                {
                    // 绘制默认的列表项
                    DrawDefaultItem(hdcDst, nIndex, ref prcItem, ref prcWin, ref  prcUpdate);
                }
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        #endregion

        /// <summary>
        /// 获取指定索引处的列表项高度
        /// </summary>
        /// <param name="index">列表项索引</param>
        /// <returns>返回此列表项高度</returns>
        public abstract int GetItemHeight(int index);
        /// <summary>
        /// 判断给定的项目索引是否存在
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public bool ContainsItem(int index)
        {
            if (index < 0 || index >= Items.Count)
                return false;

            return true;
        }
        /// <summary>
        /// 引发 ItemSelected 事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnItemSelected(ItemSelectedEventArgs e)
        {
            if (ItemSelected != null)
            {
                ItemSelected(this, e);
            }
        }
        /// <summary>
        /// 绘制默认列表项
        /// </summary>
        /// <param name="hdcDst">设备上下文句柄</param>
        /// <param name="nIndex">要绘制的列表项索引</param>
        /// <param name="prcItem">列表项所在矩形</param>
        /// <param name="prcWin">列表控件所在矩形</param>
        /// <param name="prcUpdate">待更新的矩形区域</param>
        protected abstract void DrawDefaultItem(IntPtr hdcDst, int nIndex, ref RECT prcItem, ref RECT prcWin, ref RECT prcUpdate);
        /// <summary>
        /// 绘制列表项
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnDrawItem(DrawItemEventArgs e)
        {
            if (!e.NeedRedrawItem())
                return;

            // 引发DrawItem 事件
            if (this.DrawItem != null)
            {
                this.DrawItem(this, e);
            }
        }
        /// <summary>
        /// 计算某一坐标出的列表项的索引
        /// </summary>
        /// <param name="xPos">X坐标</param>
        /// <param name="yPos">Y坐标</param>
        /// <returns>列表项索引</returns>
        public abstract int CalcItemIndexOfPos(int xPos, int yPos);
        /// <summary>
        /// 计算指定项所在矩形
        /// </summary>
        /// <param name="index">列表项索引</param>
        /// <returns></returns>
        public abstract Rectangle CalcItemRectangle(int index);
        /// <summary>
        /// 将指定索引的列表项设置为无效，在下次刷新时会重绘
        /// </summary>
        /// <param name="index">列表项索引</param>
        public abstract void InvalidateItem(int index);
        /// <summary>
        /// 引发 Click 事件
        /// </summary>
        /// <param name="e"></param>
        protected virtual void OnClick(ListBoxClickEventArgs e)
        {
            if(Click!=null)
            {
                Click(this, e);
            }
        }
        /// <summary>
        /// 销毁资源
        /// </summary>
        /// <param name="disposing"></param>
        protected override void Dispose(bool disposing)
        {
            try
            {
                Items.Clear();
            }
            catch (System.Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
            base.Dispose(disposing);
        }
        #endregion
    }
}
